package com.shareloke.server.tools

import com.google.common.collect.HashBiMap
import com.google.common.collect.Maps
import com.google.gson.Gson
import com.shareloke.server.netty.model.SocketMessage
import com.shareloke.server.netty.model.WebsocketChannel
import io.netty.channel.Channel
import io.netty.channel.ChannelId
import io.netty.channel.group.ChannelGroup
import io.netty.channel.group.DefaultChannelGroup
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
import io.netty.util.concurrent.GlobalEventExecutor

/**
 *
 *  描述：
 *
 * @author wlp
 * @version 1.0.0
 * @date 2021/7/13 上午 09:40
 */
object MyChannelManager {

    private val channelGroup: ChannelGroup = DefaultChannelGroup(GlobalEventExecutor.INSTANCE)
    private val USER_MAP = Maps.synchronizedBiMap(HashBiMap.create<ChannelId, String>())

    /**
     *
     *  方法描述：添加一个系统默认的channel
     *
     * @param userId  用户ID
     * @param channel 通道
     * @author wlp
     * @date 2021/7/13 上午 09:48
     */
    fun addChannel(userId: String, channel: Channel) {
        addWebsocketChannel(WebsocketChannel(userId, channel))
    }

    /**
     *
     *  方法描述：添加一个构建好的WebsocketChannel
     *
     * @param websocketChannel 自定义
     * @author wlp
     * @date 2021/7/13 上午 09:48
     */
    private fun addWebsocketChannel(websocketChannel: WebsocketChannel) {
        val userId: String = websocketChannel.userId
        val uid = userId.trim()
        if ("" == uid) {
            throw RuntimeException("userId 不能为空")
        }
        channelGroup.add(websocketChannel)
        USER_MAP[websocketChannel.id()] = uid
    }

    /**
     *
     *  方法描述：查找Channel
     *
     * @param channelId channelId
     * @return WebsocketChannel
     * @author wlp
     * @date 2021/7/13 上午 09:48
     */
    private fun find(channelId: ChannelId?): WebsocketChannel? {
        val channel = channelGroup.find(channelId)
        return if (channel is WebsocketChannel) {
            channel
        } else {
            null
        }
    }

    /**
     *
     *  方法描述：根据channel获取用户id
     *
     * @param channel channel
     * @return String
     * @author wlp
     * @date 2021/7/13 上午 09:47
     */
    fun getUserId(channel: Channel): String {
        return getUserId(channel.id())
    }

    /**
     *
     *  方法描述：根据channelId获取用户id
     *
     * @param channelId channelId
     * @return String
     * @author wlp
     * @date 2021/7/13 上午 09:47
     */
    private fun getUserId(channelId: ChannelId): String {
        val websocketChannel = find(channelId)
        return if (null == websocketChannel) {
            val userId = USER_MAP[channelId]
            if (null == userId || "" == userId) {
                "unknown"
            } else {
                userId
            }
        } else {
            websocketChannel.userId
        }
    }

    /**
     *
     *  方法描述：根据ChannelId移除Channel
     *
     * @param channelId ChannelId
     * @author wlp
     * @date 2021/7/13 上午 09:46
     */
    fun removeChannel(channelId: ChannelId) {
        val channel = channelGroup.find(channelId)
        if (null == channel) {
            USER_MAP.remove(channelId)
            return
        }
        if (channel is WebsocketChannel) {
            removeWebsocketChannel(channel)
        } else {
            channelGroup.remove(channel)
        }
    }

    /**
     *
     *  方法描述：移除WebsocketChannel
     *
     * @param websocketChannel 自定义的Channel
     * @author wlp
     * @date 2021/7/13 上午 09:45
     */
    private fun removeWebsocketChannel(websocketChannel: WebsocketChannel?) {
        if (null == websocketChannel || !channelGroup.contains(websocketChannel)) {
            return
        }
        val channelId: ChannelId = websocketChannel.id()
        channelGroup.remove(websocketChannel)
        USER_MAP.remove(channelId)
    }

    /**
     *
     *  方法描述：客户端总数
     *
     * @return int
     * @author wlp
     * @date 2021/7/13 上午 09:46
     */
    fun size(): Int {
        return channelGroup.size
    }

    /**
     *
     *  方法描述：群发消息
     *
     * @param msg 消息
     * @author wlp
     * @date 2021/7/13 上午 09:45
     */
    fun sendAll(msg: SocketMessage) {
        channelGroup.writeAndFlush(TextWebSocketFrame(Gson().toJson(msg)))
    }

    /**
     *
     *  方法描述：发送给指定用户
     *
     * @param msg    消息
     * @param userId 用户ID
     * @author wlp
     * @date 2021/7/13 上午 11:59
     */
    fun sendOne(msg: SocketMessage, userId: String) {
        if (USER_MAP.containsValue(userId)) {
            channelGroup.find(USER_MAP.inverse()[userId]).writeAndFlush(TextWebSocketFrame(Gson().toJson(msg)))
        } else {
            println("用户：$userId 未上线")
        }
    }
}